#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h> /* See NOTES */
#include <unistd.h>
#include <string.h>
#include <stdio.h>
/*
Create_TCP_Server：创建一个TCP服务器
Param:
IP: 指定服务器的IP地址
就是你运行服务器程序的那个设备的IP(PC)
port: 端口，指定网络应用程序的端口号 1~65535
用1024以上的端口号
Retval:
执行成功，返回服务器的套接字描述符
执行失败，返回-1
*/
int Create_TCP_Server(char *IP, int port)
{
    // 定义一个以太网地址结构体变量
    struct sockaddr_in SAddr;
    int sockfd; // 创建保存套接字接口的文件描述符
    int flag = 0;
    /* 1.创建套接字(创建网络通信接口) */
    // 创建了一个 IPV4的流式套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) // 判断有无创建成功
    {
        printf("Sever socket create failed\n");
        return -1;
    }

    // 2.用bind 绑定网络应用地址(以便其他应用找到本程序的通信接口)
    // 首先给以太网地址结构体变量 赋值
    SAddr.sin_family = AF_INET; // 指定协议族为IPV4
    // htons将本地字节序的整数部分 转换成 网络字节序
    SAddr.sin_port = htons(port);
    // inet_addr将点分十进制的IP转换成一个长整型数
    SAddr.sin_addr.s_addr = inet_addr(IP);
    // 使用bind函数把指定的ip地址，绑定到sockfd指定的套接字上
    flag = bind(sockfd, (struct sockaddr *)&SAddr,sizeof(SAddr));
    if (flag == -1)
    {
        printf("Sever bind failed\n");
        close(sockfd);
        return -1;
    }
    /*3. listen 设置监听
    内核监听是否有客服端向服务器发起连接请求
    */
    flag = listen(sockfd, 10); // 设置处理个数为10个
    if (flag == -1)
    {
        printf("Sever listen failed\n");
        close(sockfd);
        return -1;
    }
    return sockfd; // 返回套接字描述符，方便后续数据收发
}
int main()
{
    int sockfd; // 创建保存套接字接口的文件描述符
    int connfd; // 创建链接套接字描述符
    int money = 0;
    int sum = 0;
    ssize_t rsize = 0;
    unsigned char buf[256] = {0};

    /* 1. 创建一个TCP服务器 */
    // 以PC来运行服务器程序
    sockfd = Create_TCP_Server("192.168.31.17", 8899);
    if (sockfd == -1)
    {
        printf("Create_TCP_Server failed\n");
        return -1;
    }
    // 2. 等待客户端的连接请求，并与客户端建立连接
    while (1)
    {
        /*
        accept
        其返回值就是，通一个用来与客户端通信的 描述符
        称为链接套接字描述符 connfd
        服务器与客户端得到数据传输，通过accept函数的
        返回值，进行read/write
        write(connfd)， 发送数据给客户端
        read(connfd)，从客户端接收数据
        */
        // 后两个参数为null
        // 表示不用记录客户端的地址信息、地址长度
        connfd = accept(sockfd, NULL, NULL);
        if (connfd == -1)
        {
            printf("accept failed\n");
            close(sockfd);
            return -1;
        }
        printf("有客户端连接成功\n");
        // 3.根据需求，完成与客户端的通信
        while (1)
        {
            // 服务器发送一个hello给客户端
            rsize = write(connfd, "hello", 6);
            if (rsize <= 0)
            {
                printf("write to client failed\n");
                close(sockfd);
                close(connfd);
                return -1;
            }

            // 接收客户端的数据，read，类似
            memset(buf, 0, sizeof(buf));    // 将buf空间数据全部清0
            rsize = read(connfd, buf, 256); // 接收客户端数据
            
            if (rsize <= 0)
            {
                printf("read from client failed\n");
                close(sockfd);
                close(connfd);
                return -1;
            }
            printf("从客户端接收到%ld个字节数据: %s\n", rsize,buf );
            if (strcmp(buf, "自煎一面黄") == 0)
            {
                money = 35;
            }
            else if (strcmp(buf, "西兰花拌虾仁") == 0)
            {
                money = 42;
            }
            else if (strcmp(buf, "中式辣萝卜") == 0)
            {
                money = 25;
            }
            else if (strcmp(buf, "冰糖糯米藕") == 0)
            {
                money = 45;
            }
            else if (strcmp(buf, "口水鸡") == 0)
            {
                money = 68;
            }
            else if (strcmp(buf, "皮蛋豆腐") == 0)
            {
                money = 32;
            }
            sum = sum + money;
            printf("总价为:%d\n" , sum);
            // 自行定义一个通信结束的标准
            // 比如，客户端发一个 bye 过来，就结束通信
            if (strcmp(buf, "bye") == 0)
            {
                close(connfd);
                break;
            }
        }
    }
    /* 服务器结束使用 */
    close(sockfd);
}